#ifndef VENDOR_ECARX_XMA_AUDIOCONTROL_V1_0_ECARXAUDIOCONTROL_H
#define VENDOR_ECARX_XMA_AUDIOCONTROL_V1_0_ECARXAUDIOCONTROL_H

#include <vendor/ecarx/xma/audiocontrol/1.0/IEcarxAudioControl.h>
#include <hidl/Status.h>

#include "McuControl.h"

namespace vendor {
namespace ecarx {
namespace xma {
namespace audiocontrol {
namespace V1_0 {
namespace impl {

using namespace android;
using namespace android::hardware;

class HalClient : public android::RefBase {
public:
    HalClient(const sp<IEcarxAudioControlXcallCallback> &callback)
        : mCallback(callback) {}
    virtual ~HalClient() {}
public:
    sp<IEcarxAudioControlXcallCallback> getCallback() const {
        return mCallback;
    }
private:
    const sp<IEcarxAudioControlXcallCallback> mCallback;
};

using ClientId = uint64_t;

class EcarxAudioControl : public IEcarxAudioControl {

public:
    // Methods from ::vendor::ecarx::xma::audiocontrol::V1_0::IEcarxAudioControl follow.
    Return<void> setAudioSource(AudioSourceType source) override;
    Return<void> setMuteOnOff(SourceType channel, OnOff1 status) override;
    Return<void> adjustVolume(SourceType channel, uint32_t step) override;
    Return<void> setFader(uint32_t step) override;
    Return<void> setBalance(uint32_t step) override;
    Return<void> setFaderBalanceDirect(uint32_t fader, uint32_t balance) override;
    Return<void> setBass(uint32_t step) override;
    Return<void> setMiddle(uint32_t step) override;
    Return<void> setTreble(uint32_t step) override;
    Return<void> setEqualizerMode(EqType mode) override;
    Return<void> setLoudness(OnOff2 loudness) override;
    Return<void> mixSource(MixType source, MixStatus status) override;
    Return<void> audioSettingRecovery() override;
    Return<void> setSeatOptimization(SeatType seat) override;
    Return<void> setVehicleSpeedLevel(VslType level) override;
    Return<void> setClariFi(OnOff1 status) override;
    Return<void> setLogicalSeven(OnOff1 status) override;
    Return<void> getAudioStatus(getAudioStatus_cb _hidl_cb) override;
    Return<void> getXCallActive(XcallType type, XcallStatus status) override;
    Return<int32_t> registerXcallStatusCallback(const sp<IEcarxAudioControlXcallCallback>& callback) override;
    Return<void> unregisterXcallStatusCallback(const sp<IEcarxAudioControlXcallCallback>& callback) override;
    Return<void> setBoseRoomMode(BoseMode mode) override;
    Return<void> setCAEOn(CAEOn isOn) override;
    Return<void> setMixMode(MixMode mode) override;
    Return<void> setKTVOnOff(KTVOn on) override;
    Return<void> setSoundEnhance(SoundEnhance type) override;
    Return<void> setOperationPosition(OperaPosition position) override;
    Return<void> setHXTOnOff(HXTOn onOff) override;
    Return<void> setRNCOnOff(RNCOn rncOnOff) override;
    Return<void> setPartitionAudio(PartitionAudio partion) override;
    Return<void> setICCOnOff(ICCOn iccOnOff) override;
    Return<void> setWarnVolLevl(WarnVolLevel WarnVolLevel) override;
    Return<void> setHighEQ(HighEQ higheq) override;
    Return<void> setMaxBassLvl(MaxBassLevel maxBassLvl) override;
    Return<void> setTwoSurround(TwoSurround twosurround) override;
    Return<void> setTwoSurroundLvl(TwoSurroundLvl twosurroundLvl) override;
    Return<void> setThreeSurround(ThreeSurround threesurround) override;
    Return<void> setThreeSurroundLvl(ThreeSurroundLvl threesurroundLvl) override;
    Return<void> setSourceRear(SourceRear sourceRear) override;
    Return<void> setDuckAudioPolicy(DuckMode focusChangeHint, uint32_t db ,DuckSource source) override;
    Return<void> setSoundZone(uint32_t zone) override;

    EcarxAudioControl();
    virtual ~EcarxAudioControl();

    static void mcuCallback(status_t status);
    static void mcuErrorCallbacl(status_t err);

private:
    static ClientId getClientId(const sp<IEcarxAudioControlXcallCallback> callback);
    void onCallbackDead(uint64_t cookie);
    void removeClientLocked(ClientId clientId);
    void notifyHalClients(uint8_t status);

private:
    using OnClientDead = std::function<void(uint64_t)>;

    class DeathRecipient : public hidl_death_recipient {
    public:
        DeathRecipient(const OnClientDead& onClientDead)
            : mOnClientDead(onClientDead) {}
        ~DeathRecipient() = default;

        DeathRecipient(const DeathRecipient& ) = delete;
        DeathRecipient& operator=(const DeathRecipient&) = delete;

        void serviceDied(uint64_t cookie,
                         const wp<::android::hidl::base::V1_0::IBase>& /* who */) override {
            mOnClientDead(cookie);
        }

    private:
        OnClientDead mOnClientDead;
    };

private:
    using MuxGuard = std::lock_guard<std::mutex>;
    mutable std::mutex mLock;

    static McuControl* sMcuControl;
    static EcarxAudioControl* sInstance;
    std::map<ClientId, sp<HalClient>> mClients;
    sp<DeathRecipient> mCallbackDeathRecipient;
};

}  // namespace impl
}  // namespace V1_0
}  // namespace audiocontrol
}  // namespace xma
}  // namespace ecarx
}  // namespace vendor


#endif  // VENDOR_ECARX_XMA_AUDIOCONTROL_V1_0_ECARXAUDIOCONTROL_H
